package com.example.qihuibao.module.service

import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.*
import android_serialport_api.SerialPort
import com.example.qihuibao.utils.LogUtil
import java.io.File
import java.io.IOException
import java.lang.ref.WeakReference

/**
 * 串口读（二维码扫码）
 */
class SerialPortService : Service() {
    private var mSerialPort: SerialPort? = null
    private var callback:CallBack? = null
    private var mHandler: MyHandler? = null
    private var mReadThread: ReadThread? = null

    override fun onCreate() {
        super.onCreate()
    }

    override fun onBind(intent: Intent?): IBinder? {
        return MyBinder()
    }

    override fun onDestroy() {
        if (mReadThread != null) {
            mReadThread?.interrupt()
            mReadThread = null
        }
        if (mSerialPort != null) {
            mSerialPort!!.close()
            mSerialPort = null
        }
        if (mHandler != null) {
            mHandler!!.removeCallbacks(null)
            mHandler = null
        }
        super.onDestroy()
    }

    fun setCallback(callBack: CallBack) {
        this.callback = callBack
        //
        if (openSerialPort()) {
            this.callback?.openBack(true)
            readSerialPort()
        }else {
            this.callback?.openBack(false)
        }
    }

    private fun openSerialPort() : Boolean {
        try {
            val serialNumber = when(Build.MODEL) {
                "D2M" -> "/dev/ttyHSL0"
                else -> "/dev/ttyS3"
            }
            val baudRate = when(Build.MODEL) {
                "D2M" -> 115200
                else -> 9600
            }

            if (mSerialPort != null) {
                mSerialPort!!.close()
                mSerialPort = null
            }
            mSerialPort = SerialPort(File(serialNumber), baudRate, 0)
            if (mSerialPort?.inputStream != null) {
                return true
            }
            LogUtil.e("openSerialPort: inputStream=null")
        }catch (e:Exception) {
            LogUtil.e("openSerialPort: ${e.message}")
        }
        return false
    }

    private fun readSerialPort() {
        if (mHandler == null) {
            mHandler = MyHandler(this)
        }
        if (mSerialPort?.inputStream != null) {
            mReadThread = ReadThread()
            mReadThread!!.start()
        }
    }

    inner class MyBinder : Binder() {
        fun getService(): SerialPortService {
            return this@SerialPortService
        }
    }

    interface CallBack {
        fun openBack(success:Boolean)
        fun getCode(code:String)
    }

    /**
     * 读串口线程(处理分包问题)
     */
    inner class ReadThread : Thread() {
        private val runnable: SendRunnable = SendRunnable()
        private var beginning = false
        var buffer = ByteArray(64)
        override fun run() {
            super.run()
            while (!isInterrupted) {
                var size: Int
                try {
                    if (mSerialPort?.inputStream == null) return
                    //读取数据,同时获取数据长度(数据长度不是数组长度,而是实际接收到的数据长度),数据被读取到了缓冲区 buffer中
                    size = mSerialPort?.inputStream!!.read(buffer)
                    if (size > 0) {
                        //临时数组,将缓冲区buffer中的有效数据读取出来,临时数据长度就是接收到的数据长度。
                        val temp = ByteArray(size)
                        System.arraycopy(buffer, 0, temp, 0, size)
                        //具体注释见init方法
                        runnable.init(temp, size)
                        //如果程序第一次运行
                        if (!beginning) {
                            beginning = true
                            //运行runnable,只在第一次执行,如果重复执行虽不会抛出异常,但是也无法正常执行功能
                            mHandler?.post(runnable)
                        }
                    }
                } catch (e: IOException) {
                    e.printStackTrace()
                    return
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                }
            }
        }

        inner class SendRunnable : Runnable {
            private var lastBuffer: ByteArray? = null
            private var time = 0
            private var work = true

            //断包处理逻辑包含其中
            fun init(buffer: ByteArray?, size: Int) {
                if (lastBuffer == null) {
                    lastBuffer = buffer
                } else {
                    val lastBufferLength = lastBuffer!!.size
                    var temp: ByteArray? = ByteArray(lastBufferLength + size)
                    //先拷贝之前的数据
                    System.arraycopy(lastBuffer!!, 0, temp, 0, lastBufferLength)
                    //再拷贝刚接收到的数据
                    System.arraycopy(buffer!!, 0, temp, lastBufferLength, size)
                    lastBuffer = null
                    lastBuffer = temp
                    temp = null
                }
                work = true
                time = 0
            }

            fun reStart() {
                work = true
                time = 0
            }

            fun stop() {
                work = false
                time = 0
            }

            //接收完成后重置完整消息缓冲区
            fun reset() {
                work = false
                time = 0
                lastBuffer = null
                beginning = false
            }

            override fun run() {
                while (work) {
                    try {
                        sleep(20)
                        time += 20
                    } catch (e: InterruptedException) {
                        e.printStackTrace()
                    }
                    if (time >= 100) {
                        val sb = java.lang.StringBuilder()
                        for (b in lastBuffer!!) {
                            sb.append(b.toChar())
                        }
                        //                        Log.e("tag", ""+sb.toString());
                        reset()
                        //业务处理方法
                        callback?.getCode(sb.toString())
                    }
                }
            }
        }
    }

    /**
     * handler
     */
    internal class MyHandler(context: Context) : Handler() {
        var mActivityReference: WeakReference<Context>
        override fun handleMessage(msg: Message) {}

        init {
            mActivityReference = WeakReference(context)
        }
    }

}